﻿using Abp.Domain.Entities;
using Basefr.Core.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Basefr.Core.Contracts
{
    /// <summary>
    /// 公共Repository接口
    /// 项目中的所有Repository都必须直接或间接继承此接口
    /// </summary>
    public interface IRepository<TEntity, TPrimaryKey> : Abp.Domain.Repositories.IRepository<TEntity, TPrimaryKey>
        where TEntity : Entity<TPrimaryKey>
        where TPrimaryKey : struct
    {
        void Delete(IEnumerable<TEntity> entities);
    }

    /// <summary>
    /// 主键类型为int的Repository接口
    /// </summary>
    public interface IRepository<TEntity> : IRepository<TEntity, int>
        where TEntity : Entity<int>
    {

    }

    /// <summary>
    /// 不限定泛型类型的Repository接口
    /// 将Entity类型的确定（也就是实际Repository的实例化）推迟到每个方法执行时
    /// 如果一个Service类中涉及到的Entity类型太多，可以使用这个Repository，减少代码量
    /// 每次调用方法都将Resolve一个新的Repository实例
    /// </summary>
    public interface IRepository
    {
        IRepository<TEntity, int> GetRepository<TEntity>() where TEntity : EntityBase<int>;

        int Count<TEntity>() where TEntity : EntityBase<int>;
        int Count<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : EntityBase<int>;

        void Delete<TEntity>(int id) where TEntity : EntityBase<int>;
        void Delete<TEntity>(TEntity entity) where TEntity : EntityBase<int>;
        void Delete<TEntity>(IEnumerable<TEntity> entities) where TEntity : EntityBase<int>;
        void Delete<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : EntityBase<int>;

        TEntity FirstOrDefault<TEntity>(int id) where TEntity : EntityBase<int>;
        TEntity FirstOrDefault<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : EntityBase<int>;

        TEntity Single<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : EntityBase<int>;

        TEntity Get<TEntity>(int id) where TEntity : EntityBase<int>;
        IQueryable<TEntity> GetAll<TEntity>() where TEntity : EntityBase<int>;
        IQueryable<TEntity> GetAllIncluding<TEntity>(params Expression<Func<TEntity, object>>[] propSelectors) where TEntity : EntityBase<int>;
        List<TEntity> GetAllList<TEntity>() where TEntity : EntityBase<int>;
        List<TEntity> GetAllList<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : EntityBase<int>;

        TEntity Insert<TEntity>(TEntity entity) where TEntity : EntityBase<int>;
        int InsertAndGetId<TEntity>(TEntity entity) where TEntity : EntityBase<int>;

        TEntity Update<TEntity>(TEntity entity) where TEntity : EntityBase<int>;
        TEntity Update<TEntity>(int id, Action<TEntity> action) where TEntity : EntityBase<int>;
    }

}
